use core::str;
use log::error;
use rumqttc::v5::{AsyncClient, EventLoop, MqttOptions};
use std::{sync::OnceLock, time::Duration};
use tauri::{AppHandle, Emitter};

use crate::RUNTIME;

#[tauri::command]
pub fn start_mqtt(app: AppHandle, user_id: &str) {
    init(app, user_id);
}

#[tauri::command]
pub async fn publish(topic: String) {
    match CLIENT.get() {
        Some(client) => {
            let topic = topic;
            if let Err(err) = client
                .subscribe(topic, rumqttc::v5::mqttbytes::QoS::AtMostOnce)
                .await
            {
                error!("error => {}", err);
            }
        }
        _ => {
            error!("MQTT client is not configured");
        }
    }
}

static CLIENT: OnceLock<AsyncClient> = OnceLock::new();

fn init(app: AppHandle, user_id: &str) {
    let mut mqttoptions = MqttOptions::new(user_id, "web.yunnet.top", 12883);
    mqttoptions
        .set_keep_alive(Duration::from_secs(5))
        .set_credentials("test01", "123456");
    let (client, event_loop) = AsyncClient::new(mqttoptions, 10);
    match CLIENT.set(client) {
        Ok(_ok) => {

        },
        Err(error) => {
            error!("error => {:?}", error);
        },
    };
    let runtime = &RUNTIME;
    runtime.spawn(subscribe(app, event_loop));
}

pub async fn subscribe(app: AppHandle, mut event_loop: EventLoop) {
    loop {
        let notification = event_loop.poll().await;
        match notification {
            Ok(notification) => {
                if let rumqttc::v5::Event::Incoming(packet) = notification {
                    if let rumqttc::v5::mqttbytes::v5::Packet::Publish(publish) = packet {
                        let vec = publish.payload.to_vec();
                        let payload = String::from_utf8(vec).unwrap();
                        println!("topic = {:?}. Publish = {:?}", publish.topic, payload);
                        let topic = String::from_utf8(publish.topic.to_vec()).unwrap();
                        if topic.starts_with("/execute/message") {
                            let _ = app.emit("/execute/message", payload);
                        } else {
                            let _ = app.emit("/chat/message", payload);
                        }
                    }
                }
            }
            Err(error) => {
                println!("Notification->error = {error:?}");
                return;
            }
        }
    }
}
